#include "LCD/Lcd_Driver.h"
#include "LCD/GUI.h"
#include "delay.h"
#include "LCD/font.h"

#include <stdlib.h> 
#include <math.h> 

/**
 * @brief 将GBR格式的16位颜色值转换为RGB格式
 * @param c GBR格式颜色值（结构：G[5:0] B[4:0] R[4:0]）
 * @return RGB格式颜色值（结构：R[4:0] G[5:0] B[4:0]）
 * @note ILI93xx系列LCD的硬件颜色顺序为GBR，需软件转换
 */
uint16_t LCD_BGR2RGB(uint16_t c)
{
    uint16_t r, g, b, rgb;
    b = (c >> 0) & 0x1F;   // 提取B分量（低5位）
    g = (c >> 5) & 0x3F;   // 提取G分量（中间6位）
    r = (c >> 11) & 0x1F;  // 提取R分量（高5位）
    rgb = (b << 11) | (g << 5) | (r << 0);  // 重组为RGB格式
    return rgb;
}

/**
 * @brief 使用Bresenham算法绘制圆
 * @param X, Y 圆心坐标
 * @param R 半径
 * @param fc 填充颜色（RGB565格式）
 */
void Gui_Circle(uint16_t X, uint16_t Y, uint16_t R, uint16_t fc)
{
    unsigned short a = 0, b = R;
    int c = 3 - 2 * R;  // 初始决策参数 
 
    // 绘制八分圆（对称填充）
    while (a < b) {
        // 8个对称点绘制 
        Gui_DrawPoint(X + a, Y + b, fc);  // 第7象限
        Gui_DrawPoint(X - a, Y + b, fc);  // 第6象限 
        Gui_DrawPoint(X + a, Y - b, fc);  // 第2象限
        Gui_DrawPoint(X - a, Y - b, fc);  // 第3象限 
        Gui_DrawPoint(X + b, Y + a, fc);  // 第8象限
        Gui_DrawPoint(X - b, Y + a, fc);  // 第5象限 
        Gui_DrawPoint(X + b, Y - a, fc);  // 第1象限
        Gui_DrawPoint(X - b, Y - a, fc);  // 第4象限
 
        // Bresenham算法核心逻辑 
        if (c < 0) 
            c += 4 * a + 6;
        else {
            c += 4 * (a - b) + 10;
            b--;
        }
        a++;
    }
 
    // 处理剩余点（a == b时）
    if (a == b) {
        Gui_DrawPoint(X + a, Y + b, fc);
        Gui_DrawPoint(X - a, Y + b, fc);
        Gui_DrawPoint(X + a, Y - b, fc);
        Gui_DrawPoint(X - a, Y - b, fc);
        Gui_DrawPoint(X + b, Y + a, fc);
        Gui_DrawPoint(X - b, Y + a, fc);
        Gui_DrawPoint(X + b, Y - a, fc);
        Gui_DrawPoint(X - b, Y - a, fc);
    }
}

/**
 * @brief 使用Bresenham算法绘制直线
 * @param x0, y0 起点坐标
 * @param x1, y1 终点坐标 
 * @param Color 线条颜色（RGB565格式）
 */
void Gui_DrawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t Color)
{
    int dx = abs(x1 - x0), dy = abs(y1 - y0);
    int dx2 = dx << 1, dy2 = dy << 1;
    int x_inc = (x1 >= x0) ? 1 : -1;  // X方向步进 
    int y_inc = (y1 >= y0) ? 1 : -1;  // Y方向步进
    int error;
 
    Lcd_SetXY(x0, y0);  // 设置起点 
 
    // 斜率绝对值 <= 1（以X为步进轴）
    if (dx > dy) {
        error = dy2 - dx;
        for (int i = 0; i <= dx; i++) {
            Gui_DrawPoint(x0, y0, Color);
            if (error >= 0) {
                error -= dx2;
                y0 += y_inc;  // Y方向步进
            }
            error += dy2;
            x0 += x_inc;      // X方向步进 
        }
    }
    // 斜率绝对值 > 1（以Y为步进轴）
    else {
        error = dx2 - dy;
        for (int i = 0; i <= dy; i++) {
            Gui_DrawPoint(x0, y0, Color);
            if (error >= 0) {
                error -= dy2;
                x0 += x_inc;  // X方向步进 
            }
            error += dx2;
            y0 += y_inc;      // Y方向步进
        }
    }
}

/**
 * @brief 绘制带边框的填充矩形 
 * @param x, y 左上角坐标
 * @param w, h 宽度和高度 
 * @param bc 填充颜色（RGB565格式）
 * @note 边框颜色固定为浅灰（0xEF7D）和深灰（0x2965）
 */
void Gui_box(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t bc)
{
    // 绘制边框（模拟3D凹陷效果）
    Gui_DrawLine(x, y, x + w, y, 0xEF7D);        // 上边框（亮色）
    Gui_DrawLine(x + w - 1, y + 1, x + w - 1, y + h, 0x2965); // 右边框（暗色）
    Gui_DrawLine(x, y + h, x + w, y + h, 0x2965); // 下边框（暗色）
    Gui_DrawLine(x, y, x, y + h, 0xEF7D);        // 左边框（亮色）
    
    // 填充矩形内部
    Gui_DrawLine(x + 1, y + 1, x + w - 1, y + h - 1, bc);
}

/**
 * @brief 绘制可定制样式的矩形边框 
 * @param x, y 左上角坐标
 * @param w, h 宽度和高度
 * @param mode 样式模式：
 *             0 - 凹陷效果（亮左上，暗右下）
 *             1 - 凸起效果（暗左上，亮右下）
 *             2 - 单色边框 
 */
void Gui_box2(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t mode)
{
    switch (mode) {
        case 0:  // 凹陷效果
            Gui_DrawLine(x, y, x + w, y, 0xEF7D);
            Gui_DrawLine(x + w - 1, y + 1, x + w - 1, y + h, 0x2965);
            Gui_DrawLine(x, y + h, x + w, y + h, 0x2965);
            Gui_DrawLine(x, y, x, y + h, 0xEF7D);
            break;
        case 1:  // 凸起效果
            Gui_DrawLine(x, y, x + w, y, 0x2965);
            Gui_DrawLine(x + w - 1, y + 1, x + w - 1, y + h, 0xEF7D);
            Gui_DrawLine(x, y + h, x + w, y + h, 0xEF7D);
            Gui_DrawLine(x, y, x, y + h, 0x2965);
            break;
        case 2:  // 单色边框
            Gui_DrawLine(x, y, x + w, y, 0xFFFF);
            Gui_DrawLine(x + w, y, x + w, y + h, 0xFFFF);
            Gui_DrawLine(x, y + h, x + w, y + h, 0xFFFF);
            Gui_DrawLine(x, y, x, y + h, 0xFFFF);
            break;
    }
}

/**
 * @brief 绘制按下状态的按钮（3D凹陷效果）
 * @param x1, y1 左上角坐标 
 * @param x2, y2 右下角坐标
 * @note 使用灰度色模拟阴影（GRAY1=浅灰, GRAY2=深灰, WHITE=高光）
 */
void DisplayButtonDown(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
    Gui_DrawLine(x1, y1, x2, y1, GRAY2);      // 上边框（深灰）
    Gui_DrawLine(x1 + 1, y1 + 1, x2, y1 + 1, GRAY1); // 上内边框（浅灰）
    Gui_DrawLine(x1, y1, x1, y2, GRAY2);      // 左边框（深灰）
    Gui_DrawLine(x1 + 1, y1 + 1, x1 + 1, y2, GRAY1); // 左内边框（浅灰）
    Gui_DrawLine(x1, y2, x2, y2, WHITE);      // 下边框（白色高光）
    Gui_DrawLine(x2, y1, x2, y2, WHITE);      // 右边框（白色高光）
}

/**
 * @brief 绘制弹起状态的按钮（3D凸起效果）
 * @param x1, y1 左上角坐标 
 * @param x2, y2 右下角坐标
 */
void DisplayButtonUp(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
    Gui_DrawLine(x1, y1, x2, y1, WHITE);      // 上边框（白色高光）
    Gui_DrawLine(x1, y1, x1, y2, WHITE);      // 左边框（白色高光）
    Gui_DrawLine(x1 + 1, y2 - 1, x2, y2 - 1, GRAY1); // 下内边框（浅灰）
    Gui_DrawLine(x1, y2, x2, y2, GRAY2);      // 下边框（深灰）
    Gui_DrawLine(x2 - 1, y1 + 1, x2 - 1, y2, GRAY1); // 右内边框（浅灰）
    Gui_DrawLine(x2, y1, x2, y2, GRAY2);      // 右边框（深灰）
}


/**
 * @brief 在指定位置显示16x16像素的GBK编码汉字或ASCII字符 
 * @param x, y 显示起始坐标（左上角）
 * @param fc 字体颜色（RGB565格式）
 * @param bc 背景颜色（RGB565格式）
 * @param s 要显示的字符串（GBK编码）
 * @note 支持自动换行（遇到ASCII换行符`\r`时）
 */
// void Gui_DrawFont_GBK16(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint8_t *s)
// {
//     unsigned char i, j;
//     unsigned short k, x0 = x;  // x0记录行起始X坐标
 
//     while (*s) {
//         // ASCII字符处理（单字节）
//         if (*s < 128) {
//             k = *s;
//             if (k == 13) {  // 处理换行符`\r`
//                 x = x0;     // 回到行首
//                 y += 16;    // Y坐标下移一行 
//             } else {
//                 if (k > 32) k -= 32;  // ASCII码转字库索引（跳过前32个控制字符）
//                 else k = 0;
 
//                 // 绘制8x16 ASCII字符 
//                 for (i = 0; i < 16; i++) {
//                     for (j = 0; j < 8; j++) {
//                         if (asc16[k * 16 + i] & (0x80 >> j))  // 判断像素点是否需绘制 
//                             Gui_DrawPoint(x + j, y + i, fc);   // 绘制字体色 
//                         else if (fc != bc)                     // 背景色与字体色不同时填充 
//                             Gui_DrawPoint(x + j, y + i, bc);
//                     }
//                 }
//                 x += 8;  // 移动到下一个字符位置
//             }
//             s++;
//         }
//         // GBK汉字处理（双字节）
//         else {
//             // 在字库中查找匹配的汉字 
//             for (k = 0; k < hz16_num; k++) {
//                 if (hz16[k].Index[0] == *s && hz16[k].Index[1] == *(s + 1)) {
//                     // 绘制16x16汉字（分左右两部分）
//                     for (i = 0; i < 16; i++) {
//                         // 左半部分（8像素）
//                         for (j = 0; j < 8; j++) {
//                             if (hz16[k].Msk[i * 2] & (0x80 >> j))
//                                 Gui_DrawPoint(x + j, y + i, fc);
//                             else if (fc != bc)
//                                 Gui_DrawPoint(x + j, y + i, bc);
//                         }
//                         // 右半部分（8像素）
//                         for (j = 0; j < 8; j++) {
//                             if (hz16[k].Msk[i * 2 + 1] & (0x80 >> j))
//                                 Gui_DrawPoint(x + j + 8, y + i, fc);
//                             else if (fc != bc)
//                                 Gui_DrawPoint(x + j + 8, y + i, bc);
//                         }
//                     }
//                     break;
//                 }
//             }
//             s += 2;  // 跳过GBK双字节 
//             x += 16; // 移动到下一个汉字位置
//         }
//     }
// }

/**
 * @brief 在指定位置显示24x24像素的GBK编码汉字或ASCII字符
 * @param x, y 显示起始坐标（左上角）
 * @param fc 字体颜色（RGB565格式）
 * @param bc 背景颜色（RGB565格式）
 * @param s 要显示的字符串（GBK编码）
 * @note ASCII字符按8x16显示（与16x16函数行为一致）
 */
// void Gui_DrawFont_GBK24(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint8_t *s)
// {
//     unsigned char i, j;
//     unsigned short k;
 
//     while (*s) {
//         // ASCII字符处理（单字节）
//         if (*s < 0x80) {
//             k = *s;
//             if (k > 32) k -= 32;  // ASCII码转字库索引
//             else k = 0;
 
//             // 绘制8x16 ASCII字符 
//             for (i = 0; i < 16; i++) {
//                 for (j = 0; j < 8; j++) {
//                     if (asc16[k * 16 + i] & (0x80 >> j))
//                         Gui_DrawPoint(x + j, y + i, fc);
//                     else if (fc != bc)
//                         Gui_DrawPoint(x + j, y + i, bc);
//                 }
//             }
//             s++;
//             x += 8;
//         }
//         // GBK汉字处理（双字节）
//         else {
//             // 在字库中查找匹配的汉字 
//             for (k = 0; k < hz24_num; k++) {
//                 if (hz24[k].Index[0] == *s && hz24[k].Index[1] == *(s + 1)) {
//                     // 绘制24x24汉字（分左中右三部分）
//                     for (i = 0; i < 24; i++) {
//                         // 左8像素
//                         for (j = 0; j < 8; j++) {
//                             if (hz24[k].Msk[i * 3] & (0x80 >> j))
//                                 Gui_DrawPoint(x + j, y + i, fc);
//                             else if (fc != bc)
//                                 Gui_DrawPoint(x + j, y + i, bc);
//                         }
//                         // 中8像素 
//                         for (j = 0; j < 8; j++) {
//                             if (hz24[k].Msk[i * 3 + 1] & (0x80 >> j))
//                                 Gui_DrawPoint(x + j + 8, y + i, fc);
//                             else if (fc != bc)
//                                 Gui_DrawPoint(x + j + 8, y + i, bc);
//                         }
//                         // 右8像素
//                         for (j = 0; j < 8; j++) {
//                             if (hz24[k].Msk[i * 3 + 2] & (0x80 >> j))
//                                 Gui_DrawPoint(x + j + 16, y + i, fc);
//                             else if (fc != bc)
//                                 Gui_DrawPoint(x + j + 16, y + i, bc);
//                         }
//                     }
//                     break;
//                 }
//             }
//             s += 2;
//             x += 24;
//         }
//     }
// }

/**
 * @brief 显示32x32像素的数字（0-9）
 * @param x, y 显示起始坐标（左上角）
 * @param fc 数字颜色（RGB565格式）
 * @param bc 背景颜色（RGB565格式）
 * @param num 要显示的数字（0-9）
 * @note 数字字库需预先定义在sz32数组中 
 */
void Gui_DrawFont_Num32(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint16_t num)
{
    unsigned char i, j, k, c;
 
    // 遍历32行 
    for (i = 0; i < 32; i++) {
        // 每行4字节（32像素）
        for (j = 0; j < 4; j++) {
            c = *(sz32 + num * 32 * 4 + i * 4 + j);  // 获取字模数据 
            // 每字节8像素 
            for (k = 0; k < 8; k++) {
                if (c & (0x80 >> k))
                    Gui_DrawPoint(x + j * 8 + k, y + i, fc);
                else if (fc != bc)
                    Gui_DrawPoint(x + j * 8 + k, y + i, bc);
            }
        }
    }
}


